package com.jms.web.mvc.interceptor;

import com.jms.web.mvc.context.WebMvcContext;
import com.jms.web.mvc.handler.MethodHandler;
import com.jms.web.mvc.resolver.HandlerMethodArgumentResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;

/**
 * 通用拦截器链实现类，用于管理和执行一组符合条件的拦截器。
 * 在构造时根据请求和处理器筛选出需要应用的拦截器，并按顺序排序。
 */
public class GeneralInterceptorChain implements InterceptorChain {

    private final WebMvcContext webMvcContext;
    private final LinkedList<HandlerInterceptor> interceptors;

    /**
     * 构造方法，初始化拦截器链。
     * 从WebMvcContext中获取所有拦截器，并根据是否匹配当前请求和处理器进行筛选，
     * 然后按照拦截器定义的顺序进行排序。
     *
     * @param webMvcContext Web MVC上下文对象，包含拦截器和其他配置信息
     * @param request       HTTP请求对象
     * @param response      HTTP响应对象
     * @param handler       当前处理请求的目标处理器对象
     */
    public GeneralInterceptorChain(WebMvcContext webMvcContext, HttpServletRequest request, HttpServletResponse response, Object handler) {
        this.webMvcContext = webMvcContext;
        LinkedList<HandlerInterceptor> allInterceptors = webMvcContext.getInterceptors();
        interceptors = new LinkedList<>();
        for (HandlerInterceptor interceptor : allInterceptors) {
            if (interceptor.interceptAction(request, response, handler)) {
                interceptors.add(interceptor);
            }
        }
        // 按照拦截器的order值进行升序排序
        interceptors.sort(Comparator.comparingInt(HandlerInterceptor::order));
    }

    /**
     * 执行拦截器链中的各个拦截器。
     * 首先执行所有拦截器的preHandle方法，如果任一拦截器返回false则终止执行；
     * 如果handler是MethodHandler类型，则通过反射调用目标方法；
     * 最后依次执行所有拦截器的postHandle方法，并将最终结果写入响应。
     *
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param handler  当前处理请求的目标处理器对象
     */
    @Override
    public void doInterceptor(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 执行所有拦截器的前置处理方法
        for (HandlerInterceptor interceptor: interceptors) {
            if (!interceptor.preHandle(request, response, handler)) {
               return;
            }
        }

        // 如果处理器是MethodHandler类型，则执行目标方法
        if (handler instanceof MethodHandler) {
            MethodHandler methodHandler = (MethodHandler) handler;
            Object bean = webMvcContext.getApplicationContext().getBean(methodHandler.getBeanName());
            if (bean == null) {
                response.setStatus(500);
                return;
            }
            Exception ex = null;
            try {
                Method method = bean.getClass().getMethod(methodHandler.getMethodName(), methodHandler.getParameterTypes());
                Object result = null;
                try {
                    result = method.invoke(bean, HandlerMethodArgumentResolver.resolveArguments(request, response, method.getParameters(), methodHandler));
                } catch (Exception e) {
                    ex = e;
                }

                // 执行所有拦截器的后置处理方法
                Collections.reverse(interceptors);
                for (HandlerInterceptor interceptor: interceptors) {
                    result = interceptor.postHandle(request, response, handler, result);
                }

                if (ex != null) {
                    for (HandlerInterceptor interceptor: interceptors) {
                        interceptor.afterCompletion(request, response, handler, ex);
                    }
                    throw ex;
                }

                // 将处理结果写入响应
                if (result != null) {
                    response.getWriter().write(result.toString());
                    response.getWriter().flush();
                    response.getWriter().close();
                }

                for (HandlerInterceptor interceptor: interceptors) {
                    interceptor.afterCompletion(request, response, handler, ex);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
